package aip

import (
	"math"
)

/**
 * A cool byte cope class.
 * 一个很酷的字节处理类.
 * @contributor amin2312(aminlab@qq.com)
 * @createDate 2014-09-15
 */
type ByteCool struct {
	/**
	 * Length.
	 * 长度.
	 */
	_length int
	/**
	 * Position.
	 * 位置.
	 */
	_position int
	/**
	 * Size.
	 * 大小.
	 */
	_size int
	/**
	 * Buffer.
	 * 缓冲区.
	 */
	BUF []byte
}

/**
 * New instance.
 * 创建实例.
 */
func NewByteCool(initSize int) *ByteCool {
	p := new(ByteCool)
	p.ByteCool(initSize)
	return p
}

/**
 * New instance 2.
 * 创建实例(2).
 */
func NewByteWrap(bytes []byte) *ByteCool {
	p := new(ByteCool)
	p._length = 0
	p._position = 0
	p._size = len(bytes)
	p.BUF = bytes
	return p
}

/**
 * Constructor.
 * 构造函数.
 */
func (this *ByteCool) ByteCool(initSize int) {
	this._length = 0
	this._position = 0
	this._size = initSize
	this.BUF = make([]byte, this._size)
}

//================================================
//
//  property
//	属性
//
//================================================

/**
 * Get position.
 * 获取位置.
 */
func (this *ByteCool) GetPosition() int {
	return this._position
}

/**
 * Set position.
 * 设置位置.
 */
func (this *ByteCool) SetPosition(value int) {
	if value > this._length {
		value = this._length
	}
	this._position = value

}

/**
 * Move position.
 * 移动位置.
 */
func (this *ByteCool) MovPosition(value int) {
	value += this._position
	if value > this._length {
		value = this._length
	}
	this._position = value
}

/**
 * Get length.
 * 获取长度.
 */
func (this *ByteCool) GetLength() int {
	return this._length
}

/**
 * Set length.
 * 设置长度.
 */
func (this *ByteCool) SetLength(value int) {
	if value > this._size {
		value = this._size
	}
	this._length = value
}

/**
 * Move length.
 * 移动长度.
 */
func (this *ByteCool) MovLength(value int) {
	value += this._length
	if value > this._size {
		value = this._size
	}
	this._length = value
}

/**
 * Get size.
 * 获取大小.
 */
func (this *ByteCool) GetSize() int {
	return this._size
}

/**
 * Set size.
 * 设置大小.
 */
func (this *ByteCool) SetSize(value int) {
	if value > len(this.BUF) {
		var dest []byte = make([]byte, value)
		this.copyBytes(this.BUF, 0, dest, 0, this._length)
		this.BUF = dest
	}
	this._size = value
}

/**
 * Get the number of bytes of the readable data.
 * 获取可读字节数.
 */
func (this *ByteCool) GetBytesReadable() int {
	return this._length - this._position
}

/**
 * Get the number of bytes of the writeable data.
 * 获取可写字节数.
 */
func (this *ByteCool) GetBytesWriteable() int {
	return this._size - this._length
}

//================================================
//
//	read
//	读取
//
//================================================

/**
 * Read a byte(8 bits).
 * 读取一个字节.
 */
func (this *ByteCool) ReadInt8() int8 {
	var value int8 = int8(this.BUF[this._position])
	this.MovPosition(1)
	return int8(value)
}

/**
 * Read a unsigned byte(8 bits).
 * 读取一个无符号字节.
 */
func (this *ByteCool) ReadUint8() uint8 {
	var value uint8 = this.BUF[this._position]
	this.MovPosition(1)
	return value
}

/**
 * Read a short(16 bits).
 * 读取一个双字节.
 */
func (this *ByteCool) ReadInt16() int16 {
	var value uint16 = 0
	value |= uint16(this.BUF[this._position])
	value |= (uint16(this.BUF[this._position+1]) << 8)
	this.MovPosition(2)
	return int16(value)
}

/**
 * Read a unsigned short(16 bits).
 * 读取一个无符号双字节.
 */
func (this *ByteCool) ReadUint16() uint16 {
	var value uint16 = 0
	value |= uint16(this.BUF[this._position])
	value |= (uint16(this.BUF[this._position+1]) << 8)
	this.MovPosition(2)
	return value
}

/**
 * Read a int(32 bits).
 * 读取一个四字节.
 */
func (this *ByteCool) ReadInt32() int32 {
	var value uint32 = 0
	value |= uint32(this.BUF[this._position])
	value |= (uint32(this.BUF[this._position+1]) << 8)
	value |= (uint32(this.BUF[this._position+2]) << 16)
	value |= (uint32(this.BUF[this._position+3]) << 24)
	this.MovPosition(4)
	return int32(value)
}

/**
 * Read a unsigned int(32 bits).
 * 读取一个无符号四字节.
 */
func (this *ByteCool) ReadUint32() uint32 {
	var value uint32 = 0
	value |= uint32(this.BUF[this._position])
	value |= (uint32(this.BUF[this._position+1]) << 8)
	value |= (uint32(this.BUF[this._position+2]) << 16)
	value |= (uint32(this.BUF[this._position+3]) << 24)
	this.MovPosition(4)
	return value
}

/**
 * Read a float(32 bits).
 * 读取一个四字节浮点数.
 */
func (this *ByteCool) ReadFloat32() float32 {
	var value uint32 = 0
	value |= uint32(this.BUF[this._position])
	value |= (uint32(this.BUF[this._position+1]) << 8)
	value |= (uint32(this.BUF[this._position+2]) << 16)
	value |= (uint32(this.BUF[this._position+3]) << 24)
	this.MovPosition(4)
	return math.Float32frombits(value)
}

/**
 * Read a double(64 bits).
 * 读取一个八字节浮点数.
 */
func (this *ByteCool) ReadFloat64() float64 {
	var value uint64 = 0
	value |= uint64(this.BUF[this._position])
	value |= (uint64(this.BUF[this._position+1]) << 8)
	value |= (uint64(this.BUF[this._position+2]) << 16)
	value |= (uint64(this.BUF[this._position+3]) << 24)
	value |= (uint64(this.BUF[this._position+4]) << 32)
	value |= (uint64(this.BUF[this._position+5]) << 40)
	value |= (uint64(this.BUF[this._position+6]) << 48)
	value |= (uint64(this.BUF[this._position+7]) << 56)
	this.MovPosition(8)
	return math.Float64frombits(value)
}

/**
 * Read a binary.
 * 读取二进制流.
 */
func (this *ByteCool) ReadBin(l int) *ByteCool {
	var max int = this.GetBytesReadable()
	if l > max {
		l = max
	}

	var dest *ByteCool = NewByteCool(l)
	this.copyBytes(this.BUF, this._position, dest.BUF, 0, l)
	dest._length = l

	this.MovPosition(l)
	return dest
}

/**
 * Read a array of bytes.
 * 读取多个字节.
 */
func (this *ByteCool) ReadBytes(l int) []byte {
	var max int = this.GetBytesReadable()
	if l > max {
		l = max
	}

	var dest []byte = make([]byte, l)
	this.copyBytes(this.BUF, this._position, dest, 0, l)

	this.MovPosition(l)
	return dest
}

/**
 * Read a utf8 string.
 * 读取字符串.
 */
func (this *ByteCool) ReadUTF8(l int) string {
	var max int = this.GetBytesReadable()
	if l > max {
		l = max
	}

	var dest []byte = make([]byte, l)
	this.copyBytes(this.BUF, this._position, dest, 0, l)
	var str string = string(dest)

	this.MovPosition(l)
	return str
}

/**
 * Read a array of bytes(within length in byte array).
 * 读取字符串(携带长度).
 */
func (this *ByteCool) ReadLenUTF8() string {
	var l int = int(this.ReadUint8())
	if l == 0xFE {
		l = int(this.ReadUint16())
	} else if l == 0xFF {
		l = int(this.ReadInt32())
	}
	return this.ReadUTF8(l)
}

/**
 * Read a utf8 string(within length in byte array).
 * 读取多个字节(携带长度).
 */
func (this *ByteCool) ReadLenBytes() []byte {
	var l int = int(this.ReadUint8())
	if l == 0xFE {
		l = int(this.ReadUint16())
	} else if l == 0xFF {
		l = int(this.ReadInt32())
	}
	return this.ReadBytes(l)
}

/**
 * Read a binary(within length in byte array).
 * 读取二进制流(携带长度).
 */
func (this *ByteCool) ReadLenBin() *ByteCool {
	var l int = int(this.ReadUint8())
	if l == 0xFE {
		l = int(this.ReadUint16())
	} else if l == 0xFF {
		l = int(this.ReadInt32())
	}
	return this.ReadBin(l)
}

//================================================
//
//  write
//	写入
//
//================================================

/**
 * Write a byte(8 bits).
 * 写入一个字节.
 */
func (this *ByteCool) WriteInt8(value int8) {
	var l int = 1
	this.occupy(l)
	this.BUF[this._length] = uint8(value)
	this.MovLength(l)
}

/**
 * Write a unsigned byte(8 bits).
 * 写入一个无符号字节.
 */
func (this *ByteCool) WriteUint8(value uint8) {
	var l int = 1
	this.occupy(l)
	this.BUF[this._length] = value
	this.MovLength(l)
}

/**
 * Write a short(16 bits).
 * 写入一个双字节.
 */
func (this *ByteCool) WriteInt16(value int16) {
	var l int = 2
	this.occupy(l)
	this.BUF[this._length] = uint8(value & 0xFF)
	this.BUF[this._length+1] = uint8((uint16(value) & 0xFF00) >> 8)
	this.MovLength(l)
}

/**
 * Write a unsigned short(16 bits).
 * 写入一个无符号双字节.
 */
func (this *ByteCool) WriteUint16(value uint16) {
	var l int = 2
	this.occupy(l)
	this.BUF[this._length] = uint8(value & 0xFF)
	this.BUF[this._length+1] = uint8((value & 0xFF00) >> 8)
	this.MovLength(l)
}

/**
 * Write a int(32 bits).
 * 写入一个无符号四字节.
 */
func (this *ByteCool) WriteInt32(value int32) {
	var l int = 4
	this.occupy(l)
	this.BUF[this._length] = uint8(value & 0xFF)
	this.BUF[this._length+1] = uint8((uint32(value) & 0xFF00) >> 8)
	this.BUF[this._length+2] = uint8((uint32(value) & 0xFF0000) >> 16)
	this.BUF[this._length+3] = uint8((uint32(value) & 0xFF000000) >> 24)
	this.MovLength(l)
}

/**
 * Write a unsigned int(32 bits).
 * 写入一个无符号四字节.
 */
func (this *ByteCool) WriteUint32(value uint32) {
	var l int = 4
	this.occupy(l)
	this.BUF[this._length] = uint8(value & 0xFF)
	this.BUF[this._length+1] = uint8((value & 0xFF00) >> 8)
	this.BUF[this._length+2] = uint8((value & 0xFF0000) >> 16)
	this.BUF[this._length+3] = uint8((value & 0xFF000000) >> 24)
	this.MovLength(l)
}

/**
 * Write a float(32 bits).
 * 写入一个四字节浮点数.
 */
func (this *ByteCool) WriteFloat32(number float32) {
	var value uint32 = math.Float32bits(number)
	var l int = 4
	this.occupy(l)
	this.BUF[this._length] = uint8(value & 0xFF)
	this.BUF[this._length+1] = uint8((value & 0xFF00) >> 8)
	this.BUF[this._length+2] = uint8((value & 0xFF0000) >> 16)
	this.BUF[this._length+3] = uint8((value & 0xFF000000) >> 24)
	this.MovLength(l)
}

/**
 * Write a double(64 bits).
 * 写入一个八字节浮点数.
 */
func (this *ByteCool) WriteFloat64(number float64) {
	var value uint64 = math.Float64bits(number)
	var l int = 8
	this.occupy(l)
	this.BUF[this._length] = uint8(value & 0xFF)
	this.BUF[this._length+1] = uint8((value & 0xFF00) >> 8)
	this.BUF[this._length+2] = uint8((value & 0xFF0000) >> 16)
	this.BUF[this._length+3] = uint8((value & 0xFF000000) >> 24)
	this.BUF[this._length+4] = uint8((value & 0xFF00000000) >> 32)
	this.BUF[this._length+5] = uint8((value & 0xFF0000000000) >> 40)
	this.BUF[this._length+6] = uint8((value & 0xFF000000000000) >> 48)
	this.BUF[this._length+7] = uint8((value & 0xFF00000000000000) >> 56)
	this.MovLength(l)
}

/**
 * Write a binary.
 * 写入二进制流.
 */
func (this *ByteCool) WriteBin(value *ByteCool) {
	var l int = value._length
	if l == 0 {
		return
	}
	this.occupy(l)
	this.copyBytes(value.BUF, 0, this.BUF, this._length, l)
	this.MovLength(l)
}

/**
 * Write a utf8 string.
 * 写入字节串.
 */
func (this *ByteCool) WriteUTF8(value string) {
	var l int = len(value)
	if l == 0 {
		return
	}
	this.occupy(l)
	this.copyBytes([]byte(value), 0, this.BUF, this._length, l)
	this.MovLength(l)
}

/**
 * Write a array of bytes.
 * 写入多个字节.
 */
func (this *ByteCool) WriteBytes(value []byte) {
	var l int = len(value)
	if l == 0 {
		return
	}
	this.occupy(l)
	this.copyBytes(value, 0, this.BUF, this._length, l)
	this.MovLength(l)
}

/**
 * Write a utf8 string(within length in byte array).
 * 写入字符串(携带长度).
 */
func (this *ByteCool) WriteLenUTF8(value string) {
	var l int = len(value)
	if l > 0xFFFF {
		this.WriteUint8(0xFF)
		this.WriteInt32(int32(l))
	} else if l >= 0xFF {
		this.WriteUint8(0xFE)
		this.WriteUint16(uint16(l))
	} else {
		this.WriteUint8(uint8(l))
	}
	this.WriteUTF8(value)
}

/**
 * Write a array of bytes(within length in byte array).
 * 写入字节数组(携带长度).
 */
func (this *ByteCool) WriteLenBytes(value []byte) {
	var l int = len(value)
	if l > 0xFFFF {
		this.WriteUint8(0xFF)
		this.WriteInt32(int32(l))
	} else if l >= 0xFF {
		this.WriteUint8(0xFE)
		this.WriteUint16(uint16(l))
	} else {
		this.WriteUint8(uint8(l))
	}
	this.WriteBytes(value)
}

/**
 * Write a binary(within length in byte array).
 * 写入二进制流(携带长度).
 */
func (this *ByteCool) WriteLenBin(value *ByteCool) {
	var l int = value.GetLength()
	if l > 0xFFFF {
		this.WriteUint8(0xFF)
		this.WriteInt32(int32(l))
	} else if l >= 0xFF {
		this.WriteUint8(0xFE)
		this.WriteUint16(uint16(l))
	} else {
		this.WriteUint8(uint8(l))
	}
	this.WriteBin(value)
}

//================================================
//
//  special
//	特殊
//
//================================================

/**
 * Copy bytes.
 * 拷贝字节.
 */
func (this *ByteCool) copyBytes(src []byte, srcPos int, dst []byte, dstPos int, srcLen int) {
	copy(dst[dstPos:], src[srcPos:srcPos+srcLen])
}

/**
 * Occupy bytes.
 * 占据字节数.
 */
func (this *ByteCool) occupy(l int) {
	var need int = this._length + l // 当length == size时, 再写入一个0字节会引发出错
	if need <= this._size {
		return
	}
	var i int = 0
	var temp int = need
	for {
		temp = temp / 2
		i++
		if temp == 0 {
			break
		}
	}
	this.SetSize(1 << uint(i))
}

/**
 * Clone.
 * 克隆.
 */
func (this *ByteCool) Clone(shallow bool) *ByteCool {
	var dest *ByteCool = nil
	if shallow == true {
		dest = new(ByteCool)
		dest._length = this._length
		dest._position = 0
		dest._size = this._size
		dest.BUF = this.BUF
	} else {
		dest = NewByteCool(this._length)
		this.copyBytes(this.BUF, 0, dest.BUF, 0, this._length)
		dest._length = this._length
	}
	return dest
}
